package cn.aias.rbac.application.service;

import cn.aias.rbac.application.converter.UserConverter;
import cn.aias.rbac.application.dto.UserDTO;
import cn.aias.rbac.application.dto.UserQueryDTO;
import cn.aias.rbac.domain.model.User;
import cn.aias.rbac.domain.repository.UserRepository;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.criteria.Predicate;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@Transactional
public class UserApplicationService {
    private final UserRepository userRepository;
    private final UserConverter userConverter;

    public UserApplicationService(UserRepository userRepository, UserConverter userConverter) {
        this.userRepository = userRepository;
        this.userConverter = userConverter;
    }

    // 单个查询
    public UserDTO getById(Long id) {
        Optional<User> user = userRepository.findById(id);
        return user.map(userConverter::toDTO).orElse(null);
    }

    // 分页查询（动态条件迁移至此）
    public Page<UserDTO> getByPage(UserQueryDTO query, Pageable pageable) {
        // 构造Specification（原JpaUserRepository中的动态查询逻辑）
        Specification<User> spec = (root, cq, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (query.getUsername() != null) {
                predicates.add(cb.like(root.get("username"), "%" + query.getUsername() + "%"));
            }
            if (query.getRoleId() != null) {
                predicates.add(cb.equal(root.join("roles").get("id"), query.getRoleId()));
            }
            return cb.and(predicates.toArray(new Predicate[0]));
        };
        // 调用UserRepository的findAll方法（继承自JpaSpecificationExecutor）
        return userRepository.findAll(spec, pageable)
                .map(userConverter::toDTO);
    }

    // 新增/更新
    public UserDTO save(UserDTO userDTO) {
        User user = userConverter.toEntity(userDTO);
        return userConverter.toDTO(userRepository.save(user));
    }

    // 删除
    public void delete(Long id) {
        userRepository.deleteById(id);
    }

    @Transactional
    public void updateUser(Long userId, String username, String email) {
        // 第一次查询，获取当前版本
        User user = userRepository.findById(userId).orElseThrow();
        // 模拟其他事务在此期间修改了数据（版本号已更新）
        // 尝试更新，JPA 会自动检查版本
        user.setUsername(username);
        user.setEmail(email);
        userRepository.save(user); // 如果版本不一致，这里会抛异常
    }


}
